﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using ASPNETPerformance.App_BusinessLogic.Extensions;

namespace ASPNETPerformance.App_BusinessLogic.Navigation {
    public class NavigationClass {
        #region Class Variables

        SiteMapExtensions SiteMapExtender;

        // If you need to set these variables at runtime, use the necessary constructor(s)
        int SiteMenuLevel = 1;
        int SectionMenuLevel = 2;
        int SideMenuLevel = 3;

        #endregion

        #region Constructors

        public NavigationClass() {
            SiteMapExtender = new SiteMapExtensions();
        }

        /// <summary>
        /// You might need a few more constructors, say if you only wanted to set the side menu.
        /// This constructor is included as an example of how to set the different levels 
        /// to be displayed in each control to a value other than their defaults.
        /// </summary>
        /// <param name="levelSiteMenu"></param>
        /// <param name="levelSectionMenu"></param>
        /// <param name="levelSideMenu"></param>
        public NavigationClass( int levelSiteMenu, int levelSectionMenu, int levelSideMenu )
            : this() {
            SiteMenuLevel = levelSiteMenu;
            SectionMenuLevel = levelSectionMenu;
            SideMenuLevel = levelSideMenu;
        }

        #endregion

        #region Site Menu and Section Menu

        public void SetNodeSiteMenu( Menu m ) {
            SetSelectedMenuItem( m, SiteMenuLevel );
        }

        public void SetNodeSectionMenu( Menu m ) {
            SetSelectedMenuItem( m, SectionMenuLevel );
        }

        public void LoadSectionMenu( SiteMapDataSource dsMenu2, Repeater menu2 ) {
            SiteMapNode node1 = SiteMenuNode;
            bool bVisible = false;

            // Always check the value returned by CurrentBranchNode for null!!
            if ( node1 != null ) {
                if ( node1.HasChildNodes ) {
                    dsMenu2.StartingNodeUrl = node1.Url;
                    bVisible = true;
                }
            }
            // unless the Section Menu has nodes, hide it!
            menu2.Visible = bVisible;
        }

        public void SetNodeSectionMenu( SiteMapDataSource dsMenu2, SiteMapNode node, Repeater menu2 ) {
            SiteMapNode node1 = node;
            bool bVisible = false;

            // Always check the value returned by CurrentBranchNode for null!!
            if ( node1 != null ) {
                if ( node1.HasChildNodes ) {
                    dsMenu2.StartingNodeUrl = node1.Url;
                    bVisible = true;
                }
            }
            // unless the Section Menu has nodes, hide it!
            menu2.Visible = bVisible;
        }

        #endregion

        #region Side Menu

        public void LoadSideMenu( SiteMapDataSource dsMenu3, TreeView tv ) {
            // I get a reference to the Section Menu level node on the Current Branch
            // as this provides all the parameters I need to setup the Side Menu
            SiteMapNode node2 = SectionMenuNode;
            bool bVisible = false;

            // Always check the value returned by CurrentBranchNode for null!
            if ( node2 != null ) {
                if ( node2.HasChildNodes ) {
                    dsMenu3.StartingNodeUrl = node2.Url;
                    tv.ExpandDepth = SiteMapExtender.CurrentNodeLevel;
                    bVisible = true;
                }
            }
            // unless the Side Menu has nodes, hide it!
            tv.Visible = bVisible;
        }

        /// <summary>
        /// This method makes the side menu display as required for
        /// encephalitis.info
        /// 
        /// It expands the side menu according to SiteMap.CurrentNode
        /// 
        /// The important methods and properties of the tv.SelectedNode used are:
        /// 1. Expand():  this method ensures that the markup will be rendered for the specified node.
        /// 2. Expanded:  this property ensures that the relevant node will expand to show
        ///               the markup rendered by the Expand() method
        /// </summary>
        /// <param name="tv"></param>
        public void SetNodeSideMenu( TreeView tv ) {
            // Make sure only the currentnode is expanded.
            // If you want to set this on a per case basis, add a boolean parameter to the SetNodeSideMenu.
            tv.CollapseAll();
            if ( tv.SelectedNode != null ) {
                tv.SelectedNode.Expand();
            }
            else {
                SetSelectedTreeNode( tv );
            }

            // Now that I have my selected mode, 
            // I make sure that the TreeView's Expanded property is set to true!
            ExpandSideMenu( tv );
        }

        #endregion

        #region Helper Methods

        private void ExpandSideMenu( TreeView tv ) {
            TreeNode tn = tv.SelectedNode;
            if ( tn != null ) {
                while ( tn.Parent != null ) {
                    tn.Parent.Expanded = true;
                    tn = tn.Parent;
                }
            }
        }

        private void SetSelectedMenuItem( Menu m, int level ) {
            SiteMapNode nodeMenu = SiteMapExtender.CurrentBranchNode( level );
            if ( nodeMenu != null ) {
                // The ValuePath property for the node I am looking for in the TreeView control
                // is just the title.  This ONLY applies because there is only one level
                // to these menus.  See the code for the TreeView, where the ValuePath is more complex
                // to calculate because there are more than 1 possible level to search through.
                MenuItem mi = m.FindItem( nodeMenu.Title );
                if ( mi != null ) {
                    mi.Selected = true;
                }
            }
        }

        private void SetSelectedTreeNode( TreeView tv ) {
            if ( SiteMap.CurrentNode != null ) {
                // As there is more than one potential level to search for the node I want,
                // I use the property CurrentNodeValuePath to calculate the ValuePath
                TreeNode curr = tv.FindNode( SiteMapExtender.CurrentNodeValuePath( SideMenuLevel ) );
                if ( curr != null ) {
                    curr.Select();
                }
            }
        }

        #endregion

        #region Public Properties

        public SiteMapNode SiteMenuNode {
            get {
                return SiteMapExtender.CurrentBranchNode( SiteMenuLevel );
            }
        }

        public SiteMapNode SectionMenuNode {
            get {
                return SiteMapExtender.CurrentBranchNode( SectionMenuLevel );
            }
        }

        /// <summary>
        /// The SideMenuNode is either null or the Current Node
        /// </summary>
        public SiteMapNode SideMenuNode {
            get {
                return SiteMapExtender.CurrentBranchNode( SideMenuLevel );
            }
        }

        #endregion

    }
}